package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leyou.common.constants.RocketMQConstants;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.vo.PageResult;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.pojo.*;
import com.leyou.item.mapper.TbSpuMapper;
import com.leyou.item.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.netflix.discovery.converters.Auto;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * spu表，该表描述的是一个抽象性的商品，比如 iphone8 服务实现类
 * </p>
 *
 * @author leyou
 * @since 2020-02-29
 */
@Service
public class TbSpuServiceImpl extends ServiceImpl<TbSpuMapper, TbSpu> implements TbSpuService {
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * @param page     分页
     * @param rows     分页
     * @param key      搜索关键字
     * @param saleable 是否上下架
     * @return
     */
    @Override
    public PageResult<SpuDTO> findSpuByPage(Integer page, Integer rows, String key, Boolean saleable) {
        // 构建分页对象
        IPage<TbSpu> spuPage = new Page<>(page, rows);

        // 构建查询条件
        QueryWrapper<TbSpu> tbSpuQueryWrapper = new QueryWrapper<>();
        // 1、key 非空判断
        if (!StringUtils.isBlank(key)) {
            tbSpuQueryWrapper.lambda().like(TbSpu::getName, key);
        }
        // 2、
        if (saleable != null) {
            tbSpuQueryWrapper.lambda().eq(TbSpu::getSaleable, saleable);
        }
        // 3. 考虑排序（根据更新时间降序）
        tbSpuQueryWrapper.lambda().orderByDesc(TbSpu::getUpdateTime);
        // 执行查询
        IPage<TbSpu> page1 = this.page(spuPage, tbSpuQueryWrapper);
        // 构建DTO
        List<TbSpu> records = page1.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        // 返回数据
        List<SpuDTO> spuDTOList = BeanHelper.copyWithCollection(records, SpuDTO.class);
        // TODO 补全商品所对应的 品牌名称和 分类名称
        handleBrandAndCategory(spuDTOList);

        PageResult<SpuDTO> pageResult = new PageResult<>();
        pageResult.setItems(spuDTOList);
        pageResult.setTotal(page1.getTotal());
        pageResult.setTotalPage(page1.getPages());
        return pageResult;
    }


    @Autowired
    private TbSpuDetailService tbSpuDetailService;

    @Autowired
    private TbSkuService tbSkuService;

    /**
     * 保存商品数据，需要操作三张表
     *
     * @param spuDTO
     */
    @Override
    @Transactional
    public void saveGoods(SpuDTO spuDTO) {
        // 1、保存 spu数据
        // 1.1 DTO转化为PO
        TbSpu tbSpu = BeanHelper.copyProperties(spuDTO, TbSpu.class);
        // 1.2 保存数据
        boolean save = this.save(tbSpu);
        if (!save) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
        Long spuId = tbSpu.getId();

        // 2、保存 spuDetail
        // 2.1 从spuDTO 获取 spuDetail数据
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        // 2.2 数据转换，构建 tbSpuDetail 注意要手动添加 spu_id
        TbSpuDetail tbSpuDetail = BeanHelper.copyProperties(spuDetailDTO, TbSpuDetail.class);
        tbSpuDetail.setSpuId(spuId);
        // 2.3 保存spuDetail
        boolean save1 = tbSpuDetailService.save(tbSpuDetail);
        if (!save1) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

        // 3、保存 sku数据
        // 3.1 获取从spuDTO 获取 sku
        saveSkus(spuDTO, spuId);
        // TODO 发送同步的消息 （ES索引库新增商品，商品详情页微服务新增商品的详情页）
        rocketMQTemplate.convertAndSend(RocketMQConstants.TOPIC.ITEM_TOPIC_NAME+":"+RocketMQConstants.TAGS.ITEM_UP_TAGS,spuId);

        System.out.println("新增操作，发送消息");
    }

    /**
     * 修改商品  注意：skus 是先删除后添加
     *
     * @param spuDTO
     */
    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        Long spuId = spuDTO.getId();
        // 更新spu
        // 数据转化
        TbSpu tbSpu = BeanHelper.copyProperties(spuDTO, TbSpu.class);
        boolean update = this.updateById(tbSpu);
        if (!update) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        // 更新spudetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        System.err.println("spuDetailDTO = " + spuDetailDTO);
        TbSpuDetail spuDetail = BeanHelper.copyProperties(spuDetailDTO, TbSpuDetail.class);
        System.err.println("spuDetail = " + spuDetail);
        boolean b = tbSpuDetailService.updateById(spuDetail);
//        UpdateWrapper<TbSpuDetail> updateWrapper = new UpdateWrapper<>();
//        updateWrapper.lambda().eq(TbSpuDetail::getSpuId, spuId);
//        updateWrapper.setEntity(spuDetail);
//        boolean b = tbSpuDetailService.update(updateWrapper);
        if (!b) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        // 更新 skus
        // 根据 spuId删除 全部的skus
        boolean remove = tbSkuService.remove(new QueryWrapper<TbSku>().lambda().eq(TbSku::getSpuId, spuId));
        if (!remove) {
            throw new LyException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }
        // 添加 skus  不要忘记手动添加spuid
        saveSkus(spuDTO, spuId);
    }

    @Override
    public SpuDTO findSpuById(Long id) {

        TbSpu tbSpu = this.getById(id);
        if (tbSpu == null) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyProperties(tbSpu, SpuDTO.class);
    }


    // TODO 保存 skus集合
    private void saveSkus(SpuDTO spuDTO, Long spuId) {
        // 3.1 获取从spuDTO 获取 sku
        List<SkuDTO> skus = spuDTO.getSkus();
        // 3.2 对象转换 注意设置spu_id
        if (!CollectionUtils.isEmpty(skus)) {
            // Lambda表达式
            List<TbSku> tbSkuList = skus.stream().map(skuDTO ->
            {
                // 注意设置spu_id
                skuDTO.setSpuId(spuId);
                return BeanHelper.copyProperties(skuDTO, TbSku.class);

            }).collect(Collectors.toList());
            // 3.3 批量保存sku数据
            boolean b = tbSkuService.saveBatch(tbSkuList);
            if (!b) {
                throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
            }
        }
    }


    /**
     * 更改商品 上架状态
     *
     * @param spuID    spuid
     * @param saleable 是否上架下架标识
     */
    @Override
    public void updateSpuSaleable(Long spuID, Boolean saleable) {
        // 更新spu saleable字段
        TbSpu tbSpu = new TbSpu();
        tbSpu.setId(spuID);
        tbSpu.setSaleable(saleable);
        boolean b = this.updateById(tbSpu);
        if (!b) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        // 更新sku enable字段
        UpdateWrapper<TbSku> wrapper = new UpdateWrapper<>();
        wrapper.lambda().eq(TbSku::getSpuId, spuID);
        wrapper.lambda().set(TbSku::getEnable, saleable);

        boolean update = tbSkuService.update(wrapper);
        if (!update) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        // 当商品进行上下架操作的时候，进行ES数据同步，和页面静态化
        // 参数一：设置消息的topic以及tag,中间使用 : 分隔
        String topic = RocketMQConstants.TOPIC.ITEM_TOPIC_NAME;// 关于商品的 topic
        String tag = "";
        if (saleable){
            // 如果操作上架 (新增和修改，以及上架操作)
            tag = RocketMQConstants.TAGS.ITEM_UP_TAGS;
            System.out.println("上架操作");
        }else{
            // 如果操作下架 (下架)
            tag = RocketMQConstants.TAGS.ITEM_DOWN_TAGS;
            System.out.println("下架操作");
        }
        // 发送消息
        rocketMQTemplate.convertAndSend(topic+":"+tag,spuID);
        System.out.println("上下架操作 发送消息");
    }

    /**
     * 通过 SpuId 找 spu
     *
     * @param id
     * @return
     */
    @Override
    public SpuDetailDTO findSpuDetailBySpuId(Long id) {
        QueryWrapper<TbSpuDetail> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TbSpuDetail::getSpuId, id);
        TbSpuDetail spuDetail = tbSpuDetailService.getOne(wrapper);
        //TbSpuDetail spuDetail = tbSpuDetailService.(id);
        if (spuDetail == null) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        System.out.println(spuDetail);
        // 对象转化 返回
        return BeanHelper.copyProperties(spuDetail, SpuDetailDTO.class);
    }


    @Autowired
    private TbCategoryService categoryService;

    @Autowired
    private TbBrandService brandService;

    /**
     * 补全商品所对应的 品牌名称和 分类名称
     *
     * @param spuDTOList
     */
    private void handleBrandAndCategory(List<SpuDTO> spuDTOList) {
        // 获取分类id
        for (SpuDTO spuDTO : spuDTOList) {
            List<Long> categoryIds = spuDTO.getCategoryIds();
            // 查询分类数据
            Collection<TbCategory> tbCategories = categoryService.listByIds(categoryIds);
            // 使用 流的方式，获取分类的名字，也可以循环获取，不过效率低
            String categoryName = tbCategories.stream().map(TbCategory::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);

            // 查询【品牌数据,通过id获取
            Long brandId = spuDTO.getBrandId();
            TbBrand brand = brandService.getById(brandId);
            spuDTO.setBrandName(brand.getName());
        }
    }
}
